//////////////////////////////////////////////////////////////////
// MattiseOS Kernel
// Date: 2008
// Author: Matthew Iselin
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// at your option) any later version.
// 
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
//////////////////////////////////////////////////////////////////

#ifndef _STDARG_H_
#define _STDARG_H_

// the va_list type, which is important to us
#ifndef	_VA_LIST
#define _VA_LIST
typedef char* va_list;
#endif


// gets the amount of space required in an argument list (ie. the stack) for an argument of type t
#define __va_argsiz(t)	\
	(((sizeof(t) + sizeof(int) - 1) / sizeof(int)) * sizeof(int))

// start variable argument list processing by setting AP to point to the argument after pN.
#ifdef	__GNUC__
/*
 In GNU the stack is not necessarily arranged very neatly in order to
 pack shorts and such into a smaller argument list. Fortunately a
 neatly arranged version is available through the use of __builtin_next_arg.
*/
#define va_start(ap, pN)	\
	((ap) = ((va_list) __builtin_next_arg(pN)))
#else
/*
 For a simple minded compiler this should work (it works in GNU too for
 vararg lists that don't follow shorts and such).
*/
#define va_start(ap, pN)	\
	((ap) = ((va_list) (&pN) + __va_argsiz(pN)))

#endif


// ends processing of variable argument list. In this case we do nothing.
#define va_end(ap)	((void)0)


// increments ap to the next argument in the list while returing a pointer to what ap pointed to first,
//which is of type t.
#define va_arg(ap, t)					\
	 (((ap) = (ap) + __va_argsiz(t)),		\
	  *((t*) (void*) ((ap) - __va_argsiz(t))))

#endif
